﻿/**
* jQuery EasyUI 1.4.3
* Copyright (c) 2009-2015 www.jeasyui.com. All rights reserved.
*
* Licensed under the GPL license: http://www.gnu.org/licenses/gpl.txt
* To use it on other terms please contact us at info@jeasyui.com
* http://www.jeasyui.com/license_commercial.php
*
* jQuery EasyUI datagrid 扩展
* jeasyui.extensions.datagrid.views.transposed.js
* 开发 unrealwalker
* 由 落阳 修复完善并做成扩展
* 最近更新：2018-03-21
*
* 依赖项：
*   1、jquery.jdirk.js
*
* Copyright (c) 2018 Lixilin personal All rights reserved.
*/
(function ($) {

    $.util.namespace("$.fn.datagrid.extensions");

    var transposedDefault = {
        headerWidth: 160,
        itemWidth: 80
    };

    if (!$.fn.datagrid.extensions.views) {
        $.fn.datagrid.extensions.views = {};
    }
    $.fn.datagrid.extensions.views.transposedView = {
        //渲染之前
        onBeforeRender: function (target, rows) {
            console.log("onBeforeRender");
        },
        //渲染之后
        onAfterRender: function (target) {
            console.log("onAfterRender");
        },
        //渲染
        render: function (target, container, frozen) {
            console.log("render");
            var t = $(target),
                state = $.data(target, "datagrid"),
                opts = state.options;
            if (frozen) {
                if (!(opts.rownumbers || (opts.frozenColumns && opts.frozenColumns.length))) {
                    console.log("frozen return");
                    return;
                }
            }
            //if (!frozen) { return; }

            var headerWidth = opts.rowColumnReverse.headerWidth || transposedDefault.headerWidth,
                itemWidth = opts.rowColumnReverse.itemWidth || transposedDefault.itemWidth;
            var headerWidthIsNumberic = $.string.isNumeric(headerWidth), theHeaderWidth = $.string.toNumeric(headerWidth);
            var itemWidthIsNumberic = $.string.isNumeric(itemWidth), theItemWidth = $.string.toNumeric(itemWidth);

            var table = [];
            table.push('<table class="datagrid-btable" cellspacing="0" cellpadding="0" border="0"><tbody>');

            //渲染行号
            var rows = state.data.rows;
            if (opts.rownumbers) {
                table.push('<tr>');

                if (opts.showHeader) {
                    table.push('<td class="datagrid-header"></td>');
                }
                for (var i = 0; i < rows.length; i++) {
                    table.push('<td>');
                    if (frozen) {
                        table.push('<div class="datagrid-cell-rownumber datagrid-cell-height');
                    } else {
                        table.push('<div class="datagrid-cell-rownumber');
                    }

                    var row = rows[i];
                    var isSelected = row == t.datagrid("getSelected");
                    if (isSelected) {
                        table.push(' datagrid-row-selected');
                    } else {
                        if (i % 2 && opts.striped) {
                            table.push(' datagrid-row-alt');
                        } else {
                            table.push('');
                        }
                    }
                    table.push('>');
                    var rownumber = i + 1;
                    if (opts.pagination) {
                        rownumber += (opts.pageNumber - 1) * opts.pageSize;
                    }
                    table.push(rownumber);
                    table.push('</div>');
                    table.push('<td>');
                }
                table.push('</tr>');
            }
            //渲染数据体
            var fields = t.datagrid("getColumnFields", frozen);
            for (var j = 0; j < fields.length; j++) {
                var field = fields[j];
                var col = t.datagrid("getColumnOption", field);
                if (!col) { continue; }

                table.push('<tr>');
                if (opts.showHeader) {
                    var attr = '';
                    if (col.rowspan) { attr += 'rowspan="' + col.rowspan + '" ' };
                    if (col.colspan) { attr += 'colspan="' + col.colspan + '" ' };
                    table.push('<td class="datagrid-header" ' + attr);
                    if (col.checkbox) {
                        table.push(' field="' + col.field + '"><div class="datagrid-header-check"><input type="checkbox"/></div>');
                    } else if (col.field) {
                        table.push(' field="' + col.field + '"><div class="datagrid-cell datagrid-header-' + j + '"><span>' + col.title + '</span><span class="datagrid-sort-icon">&nbsp;</span></div>');
                    } else {
                        table.push('><div class="datagrid-cell-group">' + col.title + '</div>');
                    }
                    table.push('</td>');
                }
                for (var i = 0; i < rows.length; i++) {
                    var row = rows[i];
                    var isSelected = row == t.datagrid("getSelected"), isChecked = $.inArray(row, t.datagrid("getChecked")) > -1;
                    var style = (typeof (col.width) != "undefined" && $.string.isNumeric(col.width)) ? 'width:' + (col.width) + 'px;' : "";
                    style += 'text-align:' + (col.align || 'left');
                    if (col.styler) {
                        style += ";" + col.styler(row[field], row, i);
                    }
                    table.push('<td>');
                    table.push('<div style="' + style + '" datagrid-row-index="' + i + '" datagrid-column-index="' + j + '"');
                    if (col.checkbox) {
                        table.push('class="datagrid-cell-check');
                    } else {
                        table.push('class="datagrid-cell');
                    }
                    table.push(' datagrid-cell-' + j + '-' + i);
                    if (isSelected) {
                        table.push(' datagrid-row-selected');
                    } else {
                        if (i % 2 && opts.striped) {
                            table.push(' datagrid-row-alt');
                        } else {
                            table.push('');
                        }
                    }
                    if (frozen) {
                        table.push(' datagrid-cell-height ');
                    }
                    table.push('">');
                    if (col.checkbox) {
                        if (isChecked) {
                            table.push('<input type="checkbox" checked="checked"/>');
                        } else {
                            table.push('<input type="checkbox"/>');
                        }
                    } else if (col.formatter) {
                        table.push(col.formatter(row[field], row, i));
                    } else {
                        table.push(row[field]);
                    }
                    table.push('</div>');
                    table.push('</td>');
                }
                table.push('</tr>');
            }
            table.push('</tbody></table>');

            $(container).html(table.join(''));

            //绑定事件效果
            var panel = t.datagrid("getPanel"), viewContainer = panel.find("div.datagrid-view");
            var fieldCount = fields.length;
            for (var j = 0; j < fields.length; j++) {
                var field = fields[j];
                var col = t.datagrid("getColumnOption", field);
                if (!col) { continue; }

                if (headerWidthIsNumberic) {
                    $('.datagrid-header-' + j, container).width(theHeaderWidth);
                }
                for (var i = 0; i < rows.length; i++) {
                    var row = rows[i];
                    if (itemWidthIsNumberic) {
                        $('.datagrid-cell-' + j + '-' + i, container).width(theItemWidth);
                    }
                    $('.datagrid-cell-' + j + '-' + i, container).mouseover(function () {
                        var index = $(this).attr('datagrid-row-index');
                        for (var f = 0; f < fieldCount; f++) {
                            $('.datagrid-cell-' + f + '-' + index, viewContainer).addClass('datagrid-row-over');
                        }
                    }).mouseout(function () {
                        var index = $(this).attr('datagrid-row-index');
                        for (var f = 0; f < fieldCount; f++) {
                            $('.datagrid-cell-' + f + '-' + index, viewContainer).removeClass('datagrid-row-over');
                        }
                    }).click(function () {
                        var index = $(this).attr('datagrid-row-index');
                        if ($(this).hasClass('datagrid-row-selected')) {
                            internalFunctions.unselectCell(target, opts, index);
                        } else {
                            internalFunctions.selectCell(target, opts, index);
                        }
                        if (opts.onClickRow) {
                            opts.onClickRow.call(target, index, rows[index]);
                        }
                    }).dblclick(function () {
                        var index = $(this).attr('datagrid-row-index');
                        if (opts.onDblClickRow) {
                            opts.onDblClickRow.call(target, index, rows[index]);
                        }
                    });
                }
            }
        },

        renderRow: function (target, fields, frozen, rowIndex, rowData) { console.log("renderRow"); },

        renderFooter: function (target, container, frozen) { console.log("renderFooter"); },

        refreshRow: function (target, rowIndex) { console.log("refreshRow"); }
    };

    var internalFunctions = {
        selectCell: function (target, opts, index) {
            var state = $.data(target, "datagrid"),
                grid = state.grid,
                data = state.data,
                selectedRows = state.selectedRows;

            var tds = $('.datagrid-body div[datagrid-row-index=' + index + ']', grid);
            var ck = $('.datagrid-body div[datagrid-row-index=' + index + '] .datagrid-cell-check input[type=checkbox]', grid);
            if (opts.singleSelect) {
                $('.datagrid-body div.datagrid-row-selected', grid).removeClass('datagrid-row-selected');
                $('.datagrid-body .datagrid-cell-check input[type=checkbox]', grid).attr('checked', false);
                while (selectedRows.length > 0) {
                    selectedRows.pop();
                }
            }
            tds.addClass('datagrid-row-selected');
            ck.attr('checked', true);

            if (opts.idField) {
                var row = data.rows[index], key = row[opts.idField];
                if ($.array.contains(selectedRows, key, function (item1, item2) { return item1[opts.idField] == item2; })) { return; }
                selectedRows.push(row);
            }
            opts.onSelect.call(target, index, data.rows[index]);
        },

        unselectCell: function (target, opts, index) {
            var state = $.data(target, "datagrid"),
                grid = state.grid,
                selectedRows = state.selectedRows;

            var tds = $('.datagrid-body div[datagrid-row-index=' + index + ']', grid);
            var ck = $('.datagrid-body div[datagrid-row-index=' + index + '] .datagrid-cell-check input[type=checkbox]', grid);
            tds.removeClass('datagrid-row-selected');
            ck.attr('checked', false);

            var row = state.data.rows[index];
            if (opts.idField) {
                for (var i = 0; i < selectedRows.length; i++) {
                    var row1 = selectedRows[i];
                    if (row1[opts.idField] == row[opts.idField]) {
                        for (var j = i + 1; j < selectedRows.length; j++) {
                            selectedRows[j - 1] = selectedRows[j];
                        }
                        selectedRows.pop();
                        break;
                    }
                }
            }
            opts.onUnselect.call(target, index, row);
        },

        fixSize: function (target) {
            var t = $(target);
            //调整 datagrid-view1 (冻结列容器) 和 datagrid-view2 (常规列容器)的尺寸，以适配行列转置后的数据体尺寸
            var panel = t.datagrid("getPanel"),
                view1 = panel.find("div.datagrid-view div.datagrid-view1"),
                view2 = panel.find("div.datagrid-view div.datagrid-view2"),
                body1 = view1.find("div.datagrid-body"), header1 = body1.prev(), footer1 = body1.next(),
                body2 = view2.find("div.datagrid-body"), header2 = body2.prev(), footer2 = body2.next(),
                table1 = body1.find("table.datagrid-btable");
            var tableWidth1 = table1.width(), tableHeight1 = table1.height();
            var panelWidth = panel.width(), panelHeight = panel.height();
            console.log("tableWidth1：" + tableWidth1);
            console.log("panelWidth1:" + panel.width());
            console.log("panelWidth2:" + panel.panel("options").width);
            //得到datagrid-panel的宽度，作为body宽度
            header1.width(panelWidth); body1.width(panelWidth); footer1.width(panelWidth);
            view1.width(panelWidth);
            header2.width(panelWidth); body2.width(panelWidth); footer2.width(panelWidth);
            view2.width(panelWidth);
            //调整 datagrid-view1 中的 datagrid-body-inner 的样式，该样式原用于冻结列不显示横向滚动条，但需要预留出滚动条尺寸的位置以统一风格
            table1.parent().css("padding-bottom", "0");
            //调整 datagrid-view2 (常规列容器)的位置，以适配冻结列部分的行列转置和常规列部分的行列转置效果
            view2.css({ left: "0", top: tableHeight1 + "px" });
        }
    };

    function getSelected(target) {
        var state = $.data(target, "datagrid"),
            opts = state.options,
            grid = state.grid,
            data = state.data;
        if (opts.idField) {
            return state.selectedRows[0];
        }
        var rows = [];
        $('.datagrid-view2 .datagrid-body tr.datagrid-row-selected', grid).each(function () {
            var index = parseInt($(this).attr('datagrid-row-index'));
            if (data.rows[index]) {
                rows.push(data.rows[index]);
            }
        });
        var addedIndex = [];
        $('.datagrid-view2 .datagrid-body div.datagrid-row-selected', grid).each(function () {
            var index = parseInt($(this).attr('datagrid-row-index'));
            var found = false;
            for (var i = 0; i < addedIndex.length; i++) {
                if (addedIndex[i] == index) {
                    found = true;
                    break;
                }
            }
            if (data.rows[index] && !found) {
                rows.push(data.rows[index]);
                addedIndex.push(index);
            }
        });
        return rows.length > 0 ? rows[0] : null;
    }

    function isMultiLineHeaders(opts) {
        if (opts.columns && opts.columns.length > 1 && opts.columns[0].length && opts.columns[1].length) {
            return true;
        }
        if (opts.frozenColumns && opts.frozenColumns.length > 1 && opts.frozenColumns[0].length && opts.frozenColumns[1].length) {
            return true;
        }
        return false;
    }


    function initializeExtensions(target) {
        var t = $(target),
            state = $.data(target, "datagrid"),
            opts = state.options;

        if (opts.rowColumnReverse && opts.rowColumnReverse.enable === true) {
            if (isMultiLineHeaders(opts)) {
                throw "不支持在复杂表头的情况下使用行列转置功能";
            }
            //datagrid所在的容器（如layout-panel）在进行 resize 操作后，将自动触发 datagrid 内部 panel 对象的 onResize 事件
            //而在该 onResize 事件中，会通过 datagrid 内部的 fitGridSize 方法和 fitColumns 方法对 datagrid 进行调整尺寸
            //这样的调整将重置 本扩展在 onLoadSuccess 中追加的 fixSize 的效果
            //因此需要在 datagrid 完成初始化之后，重写 datagrid 内部 panel 对象的 onReize 事件，增加对 fixSize 的再次执行
            var panel = t.datagrid("getPanel"), optsPanel = panel.panel("options");
            _onResize = optsPanel.onResize;
            optsPanel.onResize = function (w, h) {
                if (_onResize && $.isFunction(_onResize)) {
                    _onResize.apply(this, arguments);
                }
                internalFunctions.fixSize(target);
            };
        }
    }

    function checkBeforeInitialize(opts) {
        if (opts.rowColumnReverse && opts.rowColumnReverse.enable === true) {
            if (isMultiLineHeaders(opts)) {
                throw "不支持在复杂表头的情况下使用行列转置功能";
            }
            opts.view = $.fn.datagrid.extensions.views.transposedView;

            //datagrid在render及afterRender执行完成之后，通过fixRowSize fixColumnSize等内置方法来重新计算组件尺寸
            //因此不能在afterRender中去隐藏 heander 所在的div，否则将影响 size 的重算
            //所以在 loadSuccess 中去隐藏 header
            var _onLoadSuccess = opts.onLoadSuccess;
            opts.onLoadSuccess = function () {
                if (_onLoadSuccess && $.isFunction(_onLoadSuccess)) { _onLoadSuccess.apply(this, arguments); }
                $("div.datagrid-header", $(this).parent()).hide();
                internalFunctions.fixSize(this);
            };
        }
    }


    var _datagrid = $.fn.datagrid.extensions._datagrid = $.fn.datagrid;
    $.fn.datagrid = function (options, param) {
        if (typeof options == "string") {
            return _datagrid.apply(this, arguments);
        }
        options = options || {};
        return this.each(function () {
            var jq = $(this),
                isInited = $.data(this, "datagrid") ? true : false,
                opts = isInited ? options : $.extend({},
                        $.fn.datagrid.parseOptions(this),
                        $.parser.parseOptions(this, [
                            {
                                
                            }
                        ]), options);
            if (!isInited) {
                checkBeforeInitialize(opts);
            }
            _datagrid.call(jq, opts, param);
            if (!isInited) {
                initializeExtensions(this);
            }
        });
    };
    $.union($.fn.datagrid, _datagrid);


    var defaults = {

        //  扩展 easyui-datagrid 的自定义属性，该属性表示 easyui-datagrid 的行列转置功能启用设定；其值支持以下属性：
        //      enable: Boolean 类型值，表示是否启用行列转置功能，默认为 false；
        //      headerWidth: Numberic 类型值，表示行列转置后纵向显示的表头的统一宽度，默认为 160；
        //      itemWidth: Numberic 类型值，表示行列转置后横向显示的数据行的统一宽度，默认为 80；
        rowColumnReverse: {
            enable: false,
            headerWidth: 160,
            itemWidth: 80
        }
    };

    var methods = {

        //  重写 easyui-datagrid 的源生 getSelected 方法；以支持在行列转置的情况下能够获得已选数据行；
        //  返回值：返回一个 JSON-Object，表示一个已选行数据对象；如果不存在已选行数据，则返回 null。
        getSelected: function (jq) { return getSelected(jq[0]); },

        //  扩展 easyui-datagrid 的自定义方法；修正行列转置效果下的各元素尺寸；
        //  返回值：返回表示当前 easyui-datagrid 组件的 jQuery 链式对象。
        fixReverseSize: function (jq) { return jq.each(function () { internalFunctions.fixSize(this); }); }
    };

    if ($.fn.datagrid.extensions.defaults) {
        $.extend($.fn.datagrid.extensions.defaults, defaults);
    } else {
        $.fn.datagrid.extensions.defaults = defaults;
    }

    if ($.fn.datagrid.extensions.methods) {
        $.extend($.fn.datagrid.extensions.methods, methods);
    } else {
        $.fn.datagrid.extensions.methods = methods;
    }


    $.extend($.fn.datagrid.defaults, defaults);
    $.extend($.fn.datagrid.methods, methods);

})(jQuery);